package com.lxk.seckilldemo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.alibaba.fastjson.JSON;
import com.lxk.seckilldemo.config.AccessLimit;
import com.lxk.seckilldemo.pojo.Order;
import com.lxk.seckilldemo.pojo.SeckillMessage;
import com.lxk.seckilldemo.pojo.SeckillOrder;
import com.lxk.seckilldemo.pojo.User;
import com.lxk.seckilldemo.rabbitMQ.Sender;
import com.lxk.seckilldemo.service.IGoodsService;
import com.lxk.seckilldemo.service.IOrderService;
import com.lxk.seckilldemo.service.ISeckillOrderService;
import com.lxk.seckilldemo.vo.GoodsVo;
import com.lxk.seckilldemo.vo.RespBean;
import com.lxk.seckilldemo.vo.RespBeanEnum;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/seckill")
public class SeckillController implements InitializingBean {
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private Sender sender;
    @Autowired
    private DefaultRedisScript<Long> script;
    private Map<Long,Boolean> emptySocket = new HashMap<>();

    /**
     * redis预减库存 qps 790.1
     */
    @RequestMapping(value = "/{path}/doSeckill",method = RequestMethod.POST )
    @ResponseBody
    public RespBean doStaticSeckill(@PathVariable String path, User user, Long goodsId){
        if(user==null) return RespBean.error(RespBeanEnum.ERROR);
        ValueOperations va=redisTemplate.opsForValue();
        boolean check=orderService.checkPath(user,goodsId,path);
        if(!check) return RespBean.error(RespBeanEnum.REQUEST_ILLEGL);
        GoodsVo goodsVo=goodsService.findGoodsVoById(goodsId);
        //判断是否重复抢购
        SeckillOrder seckillOrder = (SeckillOrder)va.get("order:"+user.getId()+":"+goodsVo.getId());
        if(seckillOrder!=null){
            return RespBean.error(RespBeanEnum.REPATE_ERROR);
        }
        //内存标记，减少redis操作
        if(emptySocket.get(goodsId)) return RespBean.error(RespBeanEnum.EMPTY_SOCKET);

        //预减库存
        //Long stock=va.decrement("seckillGoods:"+goodsVo.getId());
        Long stock = (Long)redisTemplate.execute(script, Collections.singletonList("seckillGoods:"+goodsVo.getId()),
                Collections.EMPTY_LIST);

        if(stock<0){
            va.increment("seckillGoods:"+goodsVo.getId());
            emptySocket.put(goodsId,true);
            return RespBean.error(RespBeanEnum.EMPTY_SOCKET);
        }
        SeckillMessage seckillMessage=new SeckillMessage(user,goodsId);

        //Order order=orderService.secKill(user,goodsVo);
        sender.sendSeckillMessage(JSON.toJSONString(seckillMessage));//生成订单，异步处理（关键）
        return RespBean.success(0);
    }
    @RequestMapping(value = "/result",method = RequestMethod.GET)
    @ResponseBody
    public RespBean getResult(User user, Long goodsId){
        if (user==null) return RespBean.error(RespBeanEnum.SESSION_ERROR);
        Long orderId=seckillOrderService.getResult(user,goodsId);
        return RespBean.success(orderId);
    }
    //获取秒杀接口
    @AccessLimit(second=5,maxCount=5,needLogin=true)
    @RequestMapping(value = "/path",method = RequestMethod.GET )
    @ResponseBody
    public RespBean getPath(User user, Long goodsId, HttpServletRequest request){
        if(user==null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        ValueOperations va=redisTemplate.opsForValue();
        //限制访问次数 5秒5次
        String uri=request.getRequestURI();
        Integer count=(Integer) va.get(uri+":"+user.getId());
        if(count==0) {
            va.set(uri+":"+user.getId(),1,5, TimeUnit.SECONDS);
        }else if(count<5){va.increment(uri+":"+user.getId());}
        else return RespBean.error(RespBeanEnum.ACCESS_LIMIT_REACHED);
        String path=orderService.createPath(user,goodsId);
        return RespBean.success(path);
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> list = goodsService.findGoodsVo();
        if(list==null) return;;
        list.forEach((goodsVo)->{
            emptySocket.put(goodsVo.getId(),false);
            redisTemplate.opsForValue().set("seckillGoods:"+goodsVo.getId(),goodsVo.getStockCount());
        });
    }
// @RequestMapping("/do_seckill")
// /**
//  * windows: qps 350.9
//  */
// public String doSeckill(Model model, User user,Long goodsId){
//     if(user==null) return "login";
//     model.addAttribute("user",user);
//     //判断库存
//     GoodsVo goodsVo=goodsService.findGoodsVoById(goodsId);
//     if(goodsVo.getGoodsStock()<1){
//         model.addAttribute("errmsg", RespBeanEnum.EMPTY_SOCKET.getMessage());
//         return "seckill_fail";
//     }
//     //判断是否重复抢购
//     SeckillOrder seckillOrder = seckillOrderService
//             .getOne(new QueryWrapper<SeckillOrder>().
//                     eq("user_id",user.getId()).
//                     eq("goods_id",goodsId));
//     if(seckillOrder!=null){
//         model.addAttribute("errmsg",RespBeanEnum.REPATE_ERROR.getMessage());
//         return "seckill_fail";
//     }
//     Order order=orderService.secKill(user,goodsVo);
//     model.addAttribute("orderInfo",order);
//     model.addAttribute("goods",goodsVo);
//     return "order_detail";
// }
//    @RequestMapping(value = "/doSeckill",method = RequestMethod.POST )
//    @ResponseBody
//    /**
//     * 静态页面 qps 443
//     */
//    public RespBean doStaticSeckill(User user, Long goodsId){
//        if(user==null) return RespBean.error(RespBeanEnum.ERROR);
//        //判断库存
//        GoodsVo goodsVo=goodsService.findGoodsVoById(goodsId);
//        if(goodsVo.getGoodsStock()<1){
//            return RespBean.error(RespBeanEnum.EMPTY_SOCKET);
//        }
//        //判断是否重复抢购
////        SeckillOrder seckillOrder = seckillOrderService
////                .getOne(new QueryWrapper<SeckillOrder>().
////                        eq("user_id",user.getId()).
////                        eq("goods_id",goodsId));
//        ValueOperations va=redisTemplate.opsForValue();
//        SeckillOrder seckillOrder = (SeckillOrder)va.get("order:"+user.getId()+":"+goodsVo.getId());
//        if(seckillOrder!=null){
//            return RespBean.error(RespBeanEnum.REPATE_ERROR);
//        }
//        Order order=orderService.secKill(user,goodsVo);
//        return RespBean.success(order);
//    }
}
